#Include ../debug.ahk

class StackNode {
  __New(val) {
    this.val := val
    this.next := ''
  }

  static BuyNode(val) {
    return StackNode(val)
  }
}

class Stack {
  __New() {
    this.top := this.baze := ''
    this.size := 0
  }

  Push(node) {
    if !this.top {
      this.top := this.baze := node
    }
    else {
      this.top.next := node
      this.top := node
    }
  }

  PushVal(val) {
    node := StackNode(val)
    if !this.top {
      this.top := this.baze := node
    }
    else {
      this.top.next := node
      this.top := node
    }
  }

  Pop() {
    if !this.baze.val
      return 'null'
    else {
      data := this.top.val
      this.top.val := ''
      cur := this.baze
      while (IsObject(cur.next) && cur.next != this.top) {
        cur := cur.next
      }
      this.top := cur
      return data
    }
  }

  Peek() {
    if !this.baze.val
      return
    return this.top.val
  }

  Traverse() {
    if !this.baze.val
      return
    cur := this.baze
    list := ''
    while IsObject(cur) {
      list .= cur.val
      cur := cur.next
    }
    return list
  }

  IsEmpty() {
    return (this.top) ? false : true
  }

}

if A_LineFile == A_ScriptFullPath {
  dibug := Debug()

  a := StackNode('a')
  b := StackNode('b')
  c := StackNode.BuyNode('c')

  ; init stack
  q := Stack()

  ; test push
  q.Push(a)
  q.Push(b)
  q.Push(c)
  q.PushVal('d')
  q.PushVal('e')
  q.PushVal('f')

  dibug.Join('--traverse-after-push')
  dibug.Join(q.Traverse())

  ; test pop
  q.Pop()
  q.Pop()
  q.Pop()
  q.Pop()

  dibug.Join('--traverse-after-pop')
  dibug.Join(q.Traverse())

  dibug.Join('--peek')
  dibug.Join(q.Peek())
  dibug.Join('--isEmpty')
  dibug.Join(q.IsEmpty())

  dibug.Log()
}